﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Common.Data;
using System.Linq.Expressions;
using Models.Entities;
using System.Web.Services;
using System.Web.Script.Services;

namespace ConnStrMgmt
{
    /// <summary>
    /// Author: Mike Barksdale
    /// Handles the process of managing connection strings. Uses jQuery to access methods
    /// asynchronously to avoid post back.
    /// </summary>
    public partial class ManageConnectionStrings : System.Web.UI.Page
    {
         protected IAdminDataProvider _dataProvider;
         protected System.Security.Principal.IPrincipal _user;

        protected void Page_Load(object sender, EventArgs e)
        {
            _dataProvider = new AdminDataProvider();
            _user = HttpContext.Current.User;

            if (!IsPostBack)
            {
                DatabaseTypeName.DataTextField = GetPropertyName(() => new DatabaseType().typeName);
                DatabaseTypeName.DataValueField = GetPropertyName(() => new DatabaseType().typeName);
                DatabaseTypeName.DataSource = _dataProvider.GetDatabaseTypes();
                DatabaseTypeName.DataBind();
            }
        }

        /// <summary>
        /// Gets the property name of a class.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="propertyExpression"></param>
        /// <returns></returns>
        public string GetPropertyName<T>(Expression<Func<T>> propertyExpression)
        {
            return (propertyExpression.Body as MemberExpression).Member.Name;
        }

        /// <summary>
        /// Accessed via AJAX. Demonstrates getting all of the connection strings for the current user.
        /// </summary>
        /// <returns>A JSON result object of the connection strings.</returns>
        [WebMethod]
        [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json, XmlSerializeString = false)]
        public static IList<ConnectionString> GetConnectionStrings()
        {
            var user = HttpContext.Current.User.Identity.Name;
            var list = new AdminDataProvider().GetConnectionStringsByUser(user);
            return list;
        }

        /// <summary>
        /// Access via AJAX. Edits a given connection string based on the connection string's name,
        /// database type, and the current user.
        /// </summary>
        /// <param name="connStrName">The name of the user's connection string</param>
        /// <param name="databaseTypeName">The type of the user's connection string</param>
        /// <returns></returns>
        /*[WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json, XmlSerializeString = false)]
        public static IList<ConnectionString> EditConnectionString(string connStrName, string databaseTypeName)
        {
            var user = HttpContext.Current.User.Identity.Name;
            var list = new AdminDataProvider().GetConnectionStringsByUser(user);
            return list;
        }*/

        /// <summary>
        /// Access via AJAX. Gets a connection string based on the current user, 
        /// the connection string's name, and database type.
        /// </summary>
        /// <param name="connStrName">The name of the user's connection string</param>
        /// <param name="databaseTypeName">The type of the user's connection string</param>
        /// <returns></returns>
        [WebMethod]
        [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json, XmlSerializeString = false)]
        public static ConnectionString GetConnectionString(string connStrName, string databaseTypeName)
        {
            var user = HttpContext.Current.User.Identity.Name;
            var connectionString = new AdminDataProvider().GetConnectionString(new ConnectionString
            {
                connStrName = connStrName,
                databaseTypeName = databaseTypeName,
                userId = user
            });

            return connectionString;
        }

        /// <summary>
        /// Access via AJAX. Deletes a connection string based on the connection string's name, 
        /// database type, and the current user.
        /// </summary>
        /// <param name="connStrName">The name of the user's connection string</param>
        /// <param name="databaseTypeName">The type of the user's connection string</param>
        /// <returns>A bool indicating whether or not the delete succeeded</returns>
        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json, XmlSerializeString = false)]
        public static bool DeleteConnectionString(string connStrName, string databaseTypeName)
        {
            var user = HttpContext.Current.User.Identity.Name;

            var result = new AdminDataProvider().DeleteConnectionString(new ConnectionString
            {
                connStrName = connStrName,
                databaseTypeName = databaseTypeName,
                userId = user
            });

            if (result.status == AdminDataProviderStatus.Success)
                return true;
            else
                return false;
        }

        /// <summary>
        /// Tests whether a connection string can actually connect to the database.
        /// </summary>
        /// <param name="connStrName">Connection string's name</param>
        /// <param name="databaseTypeName">Connection string's database type</param>
        /// <param name="connStrUserName">Connection string's user name</param>
        /// <param name="connStrPassword">Connection string's password</param>
        /// <param name="connStrServer">Connection string's server</param>
        /// <param name="connStrPort">Connection string's port</param>
        /// <param name="connStrServiceName">Connection string's service name</param>
        /// <param name="connStrDatabaseName">Connection string's database name</param>
        /// <returns>A bool indicating whether or not the test succeeded</returns>
        [WebMethod]
        [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json, XmlSerializeString = false)]
        public static bool TestConnectionString(string connStrName, string databaseTypeName,
            string connStrUserName, string connStrPassword, string connStrServer, string connStrPort,
            string connStrServiceName, string connStrDatabaseName)
        {
            var user = HttpContext.Current.User.Identity.Name;

            var result = new AdminDataProvider().TestConnectionString(new ConnectionString
            {
                connStrName = connStrName,
                databaseTypeName = databaseTypeName,
                userId = user,
                connStrUserName = connStrUserName,
                connStrPassword = connStrPassword,
                connStrServer = connStrServer,
                connStrPort = connStrPort,
                connStrServiceName = connStrServiceName,
                connStrDatabaseName = connStrDatabaseName
            });

            if (result.status == AdminDataProviderStatus.Success)
                return true;
            else
                return false;
        }

        /// <summary>
        /// OnClick handler for adding a connection string.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void AddConnStrSubmit_Click(object sender, EventArgs e)
        {
            //create the ConnectionString entity object and add it
            var result = _dataProvider.AddConnectionString(new ConnectionString
            {
                connStrName = ConnStrName.Text.Trim(),
                databaseTypeName = DatabaseTypeName.SelectedValue,
                userId = _user.Identity.Name,
                connStrUserName = ConnStrUserName.Text.Trim(),
                connStrPassword = ConnStrPassword.Text,
                connStrServer = ConnStrServer.Text.Trim(),
                connStrPort = ConnStrPort.Text.Trim(),
                connStrServiceName = ConnStrServiceName.Text.Trim(),
                connStrDatabaseName = ConnStrDatabaseName.Text.Trim(),
                createDate = DateTime.Now,
                modifiedDate = DateTime.Now,
                lastModifiedBy = _user.Identity.Name
            });

            if (result.status == AdminDataProviderStatus.Success)
                ConnStrStatus.Text = "Added Connection String";
            else
                ConnStrStatus.Text = "Failed: " + result.message;

            ConnStrStatus.Visible = true;
        }

        /// <summary>
        /// OnClick handler for editing an existing connection string
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void EditConnStrSubmit_Click(object sender, EventArgs e)
        {
            //edit the ConnectionString entity object and add it
            var result = _dataProvider.EditConnectionString(new ConnectionString
            {
                connStrName = ConnStrName.Text.Trim(),
                databaseTypeName = DatabaseTypeName.SelectedItem.Value,
                userId = _user.Identity.Name,
                connStrUserName = ConnStrUserName.Text.Trim(),
                connStrPassword = ConnStrPassword.Text,
                connStrServer = ConnStrServer.Text.Trim(),
                connStrPort = ConnStrPort.Text.Trim(),
                connStrServiceName = ConnStrServiceName.Text.Trim(),
                connStrDatabaseName = ConnStrDatabaseName.Text.Trim(),
                createDate = DateTime.Now,
                modifiedDate = DateTime.Now,
                lastModifiedBy = _user.Identity.Name
            }, OriginalConnStrName.Text, OriginalDatabaseTypeName.Text);

            if (result.status == AdminDataProviderStatus.Success)
                ConnStrStatus.Text = "Edited Connection String";
            else
                ConnStrStatus.Text = "Failed: " + result.message;

            ConnStrStatus.Visible = true;
        }
    }
}